package com.kggs.springsnmp.utils;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MessageProcessingModel;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.PDUFactory;
import org.snmp4j.util.TableEvent;
import org.snmp4j.util.TableUtils;

/**
 * @author jzj
 * @date 2020/7/30 15:23
 */
public class SnmpGet {
    public static final int DEFAULT_VERSION = SnmpConstants.version2c;
    public static final String DEFAULT_PROTOCOL = "udp";
    public static final int DEFAULT_PORT = 161;
    public static final long DEFAULT_TIMEOUT = 3 * 1000;
    public static final int DEFAULT_RETRY = 3;

    /**
     * @param ip
     * @param community
     * @return
     */
    public static CommunityTarget createDefault(String ip, String community) {
        Address address = GenericAddress.parse(DEFAULT_PROTOCOL + ":" + ip + "/" + DEFAULT_PORT);
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString(community));
        target.setAddress(address);
        target.setVersion(DEFAULT_VERSION);
        // milliseconds
        target.setTimeout(DEFAULT_TIMEOUT);
        target.setRetries(DEFAULT_RETRY);
        return target;
    }

    /**
     * 通过任意oid ,get方式请求服务器判断ip是否能ping通
     *
     * @return
     */
    public static boolean snmpPing(Long timeOut, String ip, String community, String oid) {

        CommunityTarget target = createDefault(ip, community);
        target.setTimeout(timeOut);
        Snmp snmp = null;
        try {
            PDU pdu = new PDU();
            // pdu.add(new VariableBinding(new OID(new int[]
            // {1,3,6,1,2,1,1,2})));
            pdu.add(new VariableBinding(new OID(oid)));

            DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
            snmp = new Snmp(transport);
            snmp.listen();
            pdu.setType(PDU.GET);
            ResponseEvent respEvent = snmp.send(pdu, target);
            PDU response = respEvent.getResponse();

            if (response == null) {
            } else {

                for (int i = 0; i < response.size(); i++) {
                    VariableBinding vb = response.get(i);
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (snmp != null) {
                try {
                    snmp.close();
                } catch (IOException ex1) {
                    snmp = null;
                }
            }
        }
        return false;
    }

    public static boolean snmpGet(String ip, String community, String oid) {

        CommunityTarget target = createDefault(ip, community);
        Snmp snmp = null;
        try {
            PDU pdu = new PDU();
            // pdu.add(new VariableBinding(new OID(new int[]
            // {1,3,6,1,2,1,1,2})));
            pdu.add(new VariableBinding(new OID(oid)));

            DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
            snmp = new Snmp(transport);
            snmp.listen();
            pdu.setType(PDU.GET);
            ResponseEvent respEvent = snmp.send(pdu, target);
            PDU response = respEvent.getResponse();

            if (response == null) {
            } else {
                for (int i = 0; i < response.size(); i++) {
                    VariableBinding vb = response.get(i);
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (snmp != null) {
                try {
                    snmp.close();
                } catch (IOException ex1) {
                    snmp = null;
                }
            }
        }
        return false;
    }

    /**
     * .同步GET 多个OID（v2c）
     *
     * @param ip
     * @param community
     * @param oidList
     */
    public static List<String> snmpGetList(String ip, String community, List<String> oidList) {
        List<String> snmpList = new ArrayList<>();
        CommunityTarget target = SnmpGet.createDefault(ip, community);

        Snmp snmp = null;
        try {
            PDU pdu = new PDU();

            for (String oid : oidList) {
                pdu.add(new VariableBinding(new OID(oid)));
            }

            DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
            transport.listen();
            snmp = new Snmp(transport);

            pdu.setType(PDU.GET);
            ResponseEvent respEvent = snmp.send(pdu, target);
            PDU response = respEvent.getResponse();

            if (response == null) {
            } else {
                for (int i = 0; i < response.size(); i++) {
                    VariableBinding vb = response.get(i);
                    snmpList.add(vb.getVariable() + "");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (snmp != null) {
                try {
                    snmp.close();
                } catch (IOException ex1) {
                    snmp = null;
                }
            }
        }
        return snmpList;
    }

    /**
     * 获取内存大小
     *
     * @param ip
     * @return
     */
    public static List<String> getSnmpLinux(String ip, String community) {
        List<String> oidList = new ArrayList<String>();
        // 系统基本信息
        oidList.add(".1.3.6.1.2.1.1.1.0");
        // 系统名称
        oidList.add(".1.3.6.1.2.1.1.5.0");
        // 内存大小
        oidList.add(".1.3.6.1.2.1.25.2.2.0");

        return SnmpGet.snmpGetList(ip, community, oidList);
    }

    public static int getSnmpDisk(String ip, String oid) {
      int _disk_size = 0;
        String[] oids = new String[]{oid};
        try {
            List<TableEvent> aPublic = getTable(ip, oids, "public");

            for (TableEvent event : aPublic) {
                VariableBinding[] valueBinds = event.getColumns();
                Variable value = null;
                if (valueBinds.length > 0) {
                    VariableBinding binding = valueBinds[0];
                    _disk_size += valueBinds[0].getVariable().toInt() / 262126;
                }
            }
            return _disk_size;

        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }

    public static List<TableEvent> getTable(String ip, String[] oids, String community) throws IOException {
        TransportMapping transport = null;
        Snmp snmp = null;
        CommunityTarget target;
        try {
            transport = new DefaultUdpTransportMapping();
            snmp = new Snmp(transport);//创建snmp
            snmp.listen();//监听消息
            target = new CommunityTarget();
            target.setCommunity(new OctetString(community));
            target.setRetries(2);
            target.setAddress(GenericAddress.parse("udp:" + ip + "/161"));
            target.setTimeout(8000);
            target.setVersion(SnmpConstants.version2c);
            TableUtils tableUtils = new TableUtils(snmp, new PDUFactory() {
                @Override
                public PDU createPDU(Target arg0) {
                    PDU request = new PDU();
                    request.setType(PDU.GET);
                    return request;
                }

                @Override
                public PDU createPDU(MessageProcessingModel messageProcessingModel) {
                    PDU request = new PDU();
                    request.setType(PDU.GET);
                    return request;
                }
            });
            OID[] columns = new OID[oids.length];
            for (int i = 0; i < oids.length; i++)
                columns[i] = new OID(oids[i]);
            List<TableEvent> list = tableUtils.getTable(target, columns, null, null);
            return list;
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                if (transport != null)
                    transport.close();
                if (snmp != null)
                    snmp.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args) throws UnknownHostException {
        String ip = "10.20.2.139";
        String community = "public";
        System.out.println(SnmpGet.getSnmpLinux(ip, community));
    }
}
